#include <ir/iden_stack.h>

#define CHECK_IDEN \
    Assert(this->iden_result_list.empty() == false, "iden result is empty")

namespace ir {
  void IdenStack::new_stack() {
    this->iden_result_list.push_back(IdenResult());
  }

  void IdenStack::delete_last_stack() {
    this->iden_result_list.pop_back();
  }

  void IdenStack::push(std::string iden, Reg * reg) {
    CHECK_IDEN;
    IdenStackResult iden_stack_result;
    iden_stack_result.tag = IdenStackResult::REG;
    iden_stack_result.reg = reg;
    this->iden_result_list.back().insert({iden, iden_stack_result});
  }

  void IdenStack::push(std::string iden, int int_number) {
    CHECK_IDEN;
    IdenStackResult iden_stack_result;
    iden_stack_result.tag = IdenStackResult::INT;
    iden_stack_result.int_number = int_number;
    this->iden_result_list.back().insert({iden, iden_stack_result});
  }

  void IdenStack::push(std::string iden, Reg * reg, ArrayInfo * array_info) {
    CHECK_IDEN;
    IdenStackResult iden_stack_result;
    iden_stack_result.tag = IdenStackResult::INT_ARRAY;
    iden_stack_result.int_array.reg = reg;
    iden_stack_result.int_array.array_info = array_info;
    this->iden_result_list.back().insert({iden, iden_stack_result});
  }

  void IdenStack::push(std::string iden, GlobalReg * global_reg) {
    CHECK_IDEN;
    IdenStackResult iden_stack_result;
    iden_stack_result.tag = IdenStackResult::GLOBAL_REG;
    iden_stack_result.global_reg = global_reg;
    this->iden_result_list.back().insert({iden, iden_stack_result});
  }

  void IdenStack::push(std::string iden, Func * func) {
    CHECK_IDEN;
    IdenStackResult iden_stack_result;
    iden_stack_result.tag = IdenStackResult::FUNCTION;
    iden_stack_result.func = func;
    this->iden_result_list.back().insert({iden, iden_stack_result});
  }

  IdenStackResult IdenStack::get(std::string iden) {
    IdenStackResult ret;
    ret.tag = IdenStackResult::NONE;
    for(IdenResult & iden_result : this->iden_result_list) {
      if(iden_result.find(iden) != iden_result.end()) {
        return iden_result[iden];
      }
    }
    return ret;
  }
}
